package org.xmap.ui.control;
import java.util.Vector;
import javax.microedition.lcdui.*;
import org.xmap.app.Env;
import org.xmap.ui.UIUtil;
import org.xmap.ui.base.Event;
import org.xmap.ui.base.Window;
import org.xmap.ui.listener.MenuListener;
/**
 * <p>简单菜单类，一般用于主界面中，提供一个快速显示列表菜单的方法，该菜单和View下面的菜单栏不一样。</p>
 * @author Zealot
 * @version 1.0
 */
public final class SimpleMenu extends Window {
    /**
     * 存储所有的菜单项。
     */
    private Vector content;
    /**
     * 当前选中菜单的下标。
     */
    private int index;
    /**
     * 菜单监听器。
     */
    private MenuListener listener;
    /**
     * 是否显示边框。
     */
    private boolean drawRect;
    /**
     * 是否是透明，如果透明，将不会显示背景颜色。
     */
    private boolean transparent;
    /**
     * 菜单项的高度，为菜单的高度加上间隔的高度。
     */
    private int itemHeight;
    /**
     * 当前区域能显示几行。
     */
    private int disCount;
    /**
     * 当前绘制文字的第一行在向量中的序号。
     */
    private int drawBase;
    /**
     * 文本的纵向偏移，为了让文本居中显示。
     */
    private int disOffset;
    /**
     * 横方向的对齐方式，当屏幕发生改变之后，菜单横方向的中心保持在该位置，位置为0到100，表示在屏幕的横方向的百分比。
     */
    private int alignX;
    /**
     * 纵方向的对齐方式，当屏幕发生改变之后，菜单纵方向的中心保持在该位置，位置为0到100，表示为屏幕的纵方向的百分比。
     */
    private int alignY;
    /**
     * 菜单文字的颜色。
     */
    private int textColor;
    /**
     * 边框的颜色。
     */
    private int lineColor;
    /**
     * 选中菜单文字的颜色。
     */
    private int selectedColor;
    /**
     * 选中菜单的背景颜色。
     */
    private int selectedBgColor;
    /**
     * 指定锚点横坐标、纵坐标、菜单控件宽度、菜单控件高度、菜单项高度、菜单高度和锚点类型的构造函数。
     * @param x int 锚点横坐标。
     * @param y int 锚点纵坐标。
     * @param width int 菜单控件宽度。
     * @param height int 菜单控件高度。
     * @param itemHeight int 菜单项高度。
     * @param orient int 锚点类型。
     */
    public SimpleMenu(int x, int y, int width, int height, int itemHeight, int orient) {
        super(x, y, width, height, orient);
        this.content = new Vector(8);
        this.index = -1;
        this.listener = null;
        this.drawRect = false;
        this.transparent = true;
        this.itemHeight = itemHeight;
        this.disCount = 0;
        this.drawBase = 0;
        this.disOffset = 0;
        this.alignX = -1;
        this.alignY = -1;
        this.textColor = 0x00000000;
        this.lineColor = 0xffffff00;
        this.selectedColor = 0xffff0000;
        this.selectedBgColor = 0xff888888;
        this.calcuateView();
    }
    /**
     * 设置文本区域的窗口区域。
     * @param leftUpX int 文本区域左上角横坐标。
     * @param leftUpY int 文本区域左上角纵坐标。
     * @param width int 文本区域宽度。
     * @param height int 文本区域高度。
     */
    public void setRect(int leftUpX, int leftUpY, int width, int height) {
        super.setRect(leftUpX, leftUpY, width, height);
        this.calcuateView();
    }
    /**
     * 屏幕发生改变的通知。
     * @param width int 新的屏幕宽度。
     * @param height int 新的屏幕高度。
     */
    public void sizeChanged(int width, int height) {
        if (this.alignX > 0) { // 调整横向坐标
            this.getRect().leftUp.x = (width - this.getRect().width) * this.alignX / 100;
        }
        if (this.alignY > 0) { // 调整纵向坐标
            this.getRect().leftUp.y = (height - this.getRect().height) * this.alignY / 100;
        }
    }
    /**
     * 添加一个指定名字的菜单。
     * @param name String 菜单名字。
     */
    public void addMenu(String name) {
        this.addMenu(name, null, null);
    }
    /**
     * 添加一个指定名字和图像的菜单，如果没有指定图片，则显示菜单的时候以文字的方式显示，指定了图片将显示图片。
     * @param name String 菜单名字。
     * @param normal Image 菜单的图片。
     * @param hover Image 菜单被选中的图片。
     */
    public void addMenu(String name, Image normal, Image hover) {
        ListItem li = new ListItem(0, name, normal, hover, name, null, null, null);
        this.content.addElement(li);
        if (this.index == -1) {
            this.index = 0;
        }
    }
    /**
     * 修改指定的菜单名字。
     * @param from String 修改前的菜单名字。
     * @param to String 修改后的菜单名字。
     */
    public void changeMenu(String from, String to) {
        if (from != null && to != null) {
            for (int i = 0; i < this.content.size(); i++) {
                ListItem li = (ListItem)this.content.elementAt(i);
                if (li.obj != null && li.obj.equals(from)) {
                    li.obj = to;
                    li.second1 = to;
                }
            }
        }
    }
    /**
     * 修改指定的菜单名字。
     * @param from String 修改前的菜单名字。
     * @param to String 修改后的菜单名字。
     * @param normal Image 菜单的图片。
     * @param hover Image 菜单被选中的图片。
     */
    public void changeMenu(String from, String to, Image normal, Image hover) {
        if (from != null && to != null) {
            for (int i = 0; i < this.content.size(); i++) {
                ListItem li = (ListItem)this.content.elementAt(i);
                if (li.obj != null && li.obj.equals(from)) {
                    li.obj = to;
                    li.first1 = normal;
                    li.first2 = hover;
                    li.second1 = to;
                }
            }
        }
    }
    /**
     * 移除指定名字的菜单。
     * @param name String 菜单名字。
     */
    public void removeMenu(String name) {
        for (int i = 0; i < this.content.size(); i++) {
            ListItem li = (ListItem)this.content.elementAt(i);
            if (li.obj != null && li.obj.equals(name)) {
                this.content.removeElementAt(i);
                i--;
            }
        }
    }
    /**
     * 获得选中的菜单下标。
     * @return int 选中的菜单下标。
     */
    public int getSelectIndex() {
        return this.index + this.drawBase;
    }
    /**
     * 设置选中的菜单下标。
     * @param index int 选中的菜单下标。
     */
    public void setSelectIndex(int index) {
        if (index >= this.content.size()) {
            index = this.content.size() - 1;
        }
        if (index < 0) {
            index = 0;
        }
        if (this.content.size() <= this.disCount) {
            this.drawBase = 0;
            this.index = Math.min(this.content.size() - 1, index);
        } else {
            if (index >= this.disCount) {
                this.index = this.disCount - 1;
                this.drawBase = index + 1 - this.disCount;
            } else {
                this.drawBase = 0;
                this.index = index;
            }
        }
    }
    /**
     * 选中菜单向上移动。
     */
    public void upSelectIndex() {
        if (this.index > 0) {
            this.index--;
        } else if (this.drawBase > 0) {
            this.drawBase--;
        } else {
            if (this.content.size() >= this.disCount) {
                this.index = this.disCount - 1;
                this.drawBase = this.content.size() - this.index - 1;
            } else {
                this.index = this.content.size() - 1;
                this.drawBase = 0;
            }
        }
    }
    /**
     * 选中菜单向下移动。
     */
    public void downSelectIndex() {
        if (this.index < Math.min(this.disCount, this.content.size() - this.drawBase) - 1) {
            this.index++;
        } else if (this.drawBase + this.index < this.content.size() - 1) {
            this.drawBase++;
        } else {
            if (this.content.size() > 0) {
                this.drawBase = 0;
                this.index = 0;
            } else {
                this.drawBase = 0;
                this.index = -1;
            }
        }
    }
    /**
     * 设置菜单监听器。
     * @param listener MenuListener 菜单监听器。
     */
    public void setListener(MenuListener listener) {
        this.listener = listener;
    }
    /**
     * 获得菜单监听器。
     * @return MenuListener 菜单监听器。
     */
    public MenuListener getListener() {
        return this.listener;
    }
    /**
     * 设置是否显示边框。
     * @param drawRect boolean 是否显示边框。
     */
    public void setDrawRect(boolean drawRect) {
        this.drawRect = drawRect;
    }
    /**
     * 获得是否显示边框。
     * @return boolean 是否显示边框。
     */
    public boolean getDrawRect() {
        return this.drawRect;
    }
    /**
     * 设置菜单是否为透明，透明的意思是不用背景颜色填充背景。
     * @param transparent boolean 是否透明。
     */
    public void setTransparent(boolean transparent) {
        this.transparent = transparent;
    }
    /**
     * 获得当前菜单是否为透明。
     * @return boolean 是否透明。
     */
    public boolean getTransparent() {
        return this.transparent;
    }
    /**
     * 设置菜单项的高度。
     * @param itemHeight int 菜单项高度。
     */
    public void setItemHeight(int itemHeight) {
        this.itemHeight = itemHeight;
        this.calcuateView();
    }
    /**
     * 获得菜单项的高度。
     * @return int 菜单项的高度。
     */
    public int getItemHeight() {
        return this.itemHeight;
    }
    /**
     * 设置横向对齐百分比。
     * @param alignX int 横向对齐百分比。
     */
    public void setAlignX(int alignX) {
        this.alignX = alignX;
    }
    /**
     * 获得横向对齐百分比。
     * @return int 横向对齐百分比。
     */
    public int getAlignX() {
        return this.alignX;
    }
    /**
     * 设置纵向对齐百分比。
     * @param alignY int 纵向对齐百分比。
     */
    public void setAlignY(int alignY) {
        this.alignY = alignY;
    }
    /**
     * 获得纵向对齐百分比。
     * @return int 纵向对齐百分比。
     */
    public int getAlignY() {
        return this.alignY;
    }
    /**
     * 设置菜单文字的颜色。
     * @param textColor int 菜单文字的颜色。
     */
    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }
    /**
     * 获得菜单文字的颜色。
     * @return int 菜单文字的颜色。
     */
    public int getTextColor() {
        return this.textColor;
    }
    /**
     * 设置边框的颜色。
     * @param lineColor int 边框的颜色。
     */
    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }
    /**
     * 获得边框的颜色。
     * @return int 边框的颜色。
     */
    public int getLineColor() {
        return this.lineColor;
    }
    /**
     * 设置选中菜单文字的颜色。
     * @param selectedColor int 选中菜单文字的颜色。
     */
    public void setSelectedColor(int selectedColor) {
        this.selectedColor = selectedColor;
    }
    /**
     * 获得选中菜单文字的颜色。
     * @return int 选中菜单文字的颜色。
     */
    public int getSelectedColor() {
        return this.selectedColor;
    }
    /**
     * 设置选中菜单的背景颜色。
     * @param selectedBgColor int 选中菜单的背景颜色。
     */
    public void setSelectedBgColor(int selectedBgColor) {
        this.selectedBgColor = selectedBgColor;
    }
    /**
     * 获得选中菜单的背景颜色。
     * @return int 选中菜单的背景颜色。
     */
    public int getSelectedBgColor() {
        return this.selectedBgColor;
    }
    /**
     * 绘制函数。
     * @param g Graphics 图形句柄。
     */
    public void draw(Graphics g) {
//        if (!this.show) {
//            return;
//        }
        g.setFont(Env.instance.defaultFont);
        if (!this.transparent) {
            g.setColor(this.bgColor);
            g.fillRect(0, 0, this.getRect().width, this.getRect().height);
        }
        g.translate(0, this.disOffset);
        for (int i = 0; i + this.drawBase < this.content.size() && i < this.disCount; i++) {
            ListItem li = (ListItem)this.content.elementAt(i + this.drawBase);
            if (li != null) {
                if (li.first1 != null && li.first2 != null) {
                    int cx = g.getClipX();
                    int cy = g.getClipY();
                    int cw = g.getClipWidth();
                    int ch = g.getClipHeight();
                    g.setClip(0, i * this.itemHeight,
                              this.getRect().width - 1, this.itemHeight - 1);
                    if (this.index == i) {
                        g.drawImage((Image) li.first2, 0, i * this.itemHeight, Graphics.LEFT | Graphics.TOP);
                    } else {
                        g.drawImage((Image) li.first1, 0, i * this.itemHeight, Graphics.LEFT | Graphics.TOP);
                    }
                    g.setClip(cx, cy, cw, ch);
                } else {
                    String text = null;
                    if (li.second1 != null) {
                        text = (String) li.second1;
                    } else {
                        text = (String) li.obj;
                    }
                    if (this.index == i) {
                        g.setColor(this.selectedBgColor);
                        g.fillRect(1, i * this.itemHeight + 1, this.getRect().width - 2, this.itemHeight - 2);
                        g.setColor(this.selectedColor);
                    } else {
                        g.setColor(this.textColor);
                    }
                    UIUtil.draw(g, text,
                                      this.getRect().width >> 1, i * this.itemHeight + (this.itemHeight >> 1),
                                      Graphics.HCENTER, Graphics.VCENTER);
                    g.setColor(this.lineColor);
                    g.drawRect(0, i * this.itemHeight, this.getRect().width - 1, this.itemHeight - 2);
                }
            }
        }
        g.translate(0, -this.disOffset);
        if (this.drawRect) {
            g.setColor(this.lineColor);
            g.drawRect(0, 0, this.getRect().width - 1, this.getRect().height - 1);
        }
    }
    /**
     * 简单菜单控件处理向上、向下、选中、左软键、右软键按键消息。
     * @param flag boolean 是按下还是抬起。
     * @param keyCode int 按键代码。
     * @param gameAction int 动作代码。
     * @return boolean 是否处理该事件。
     */
    public boolean keyEvent(boolean flag, int keyCode, int gameAction) {
//        if (!this.show || !this.enable) {
//            return false;
//        }
        switch (gameAction) {
        case Canvas.UP:
            if (flag) {
                this.upSelectIndex();
            }
            return true;
        case Canvas.DOWN:
            if (flag) {
                this.downSelectIndex();
            }
            return true;
        case Canvas.FIRE:
            if (flag) {
                if (this.listener != null) {
                    if (this.content.size() > 0) {
                        ListItem li = (ListItem)this.content.elementAt(this.getSelectIndex());
                        this.listener.commandEvent((String) li.obj, this);
                    }
                }
            }
            return true;
        }
        if (keyCode == Env.instance.leftSoftKey || keyCode == Env.instance.leftSoftKeySnd) {
            if (flag) {
                if (this.listener != null) {
                    if (this.content.size() > 0) {
                        ListItem li = (ListItem)this.content.elementAt(this.getSelectIndex());
                        this.listener.commandEvent((String) li.obj, this);
                    }
                }
            }
            return true;
        } else if (keyCode == Env.instance.rightSoftKey || keyCode == Env.instance.rightSoftKeySnd) {
            if (flag) {
                if (this.listener != null) {
                    if (this.content.size() > 0) {
                        ListItem li = (ListItem)this.content.elementAt(this.content.size() - 1);
                        this.listener.commandEvent((String) li.obj, this);
                    }
                }
            }
            return true;
        }
        return false;
    }
    /**
     * 触笔事件处理函数，在菜单区域内的触笔事件都被处理。
     * @param ev Event 触笔事件。
     * @return boolean 是否处理该事件。
     */
    public boolean pointerEvent(Event ev) {
//        if (!this.show || !this.enable) {
//            return false;
//        }
        switch (ev.type) {
        case Event.POINTER_PRESSED:
            if (this.getRect().collideWith(ev.param1, ev.param2)) {
                this.pointerPressedY = ev.param2;
                int y = ev.param2 - this.getRect().leftUp.y - this.disOffset;
                if (y > 0) {
                    int index = y / this.itemHeight;
                    this.index = index;
                }
                return true;
            }
            break;
        case Event.POINTER_RELEASED:
            if (this.getRect().collideWith(ev.param1, ev.param2)) {
                int y = ev.param2 - this.getRect().leftUp.y - this.disOffset;
                if (y > 0) {
                    this.index = y / this.itemHeight;
                    if (this.listener != null) {
                        ListItem li = (ListItem)this.content.elementAt(this.getSelectIndex());
                        this.listener.commandEvent((String) li.obj, this);
                    }
                }
                return true;
            }
            break;
        case Event.POINTER_DRAGGED:
            if (this.getRect().collideWith(ev.param1, ev.param2)) {
                int y = ev.param2 - this.getRect().leftUp.y - this.disOffset;
                if (y > 0) {
                    this.index = y / this.itemHeight;
                }
                return true;
            }
            break;
        }
        return false;
    }
    /**
     * 重新计算行数和纵向偏移，当行高或区域高度发生变化的时候，需要调用这个行数。
     */
    private void calcuateView() {
        this.disCount = this.getRect().height / this.itemHeight;
        this.disOffset = (this.getRect().height % this.itemHeight) >> 1;
        if (this.drawBase > 0) {
            int withoutBaseSize = this.content.size() - this.drawBase;
            if (this.disCount > withoutBaseSize) {
                this.drawBase -= (this.disCount - withoutBaseSize);
                if (this.drawBase < 0) {
                    this.drawBase = 0;
                }
            }
        }
    }
}
